@file:UseSerializers(ResourceLocationSerializer::class, ItemStackSerializer::class, TextAsJsonStringSerializer::class)

package com.lalameow.researchstation.network

import com.lalameow.researchstation.Cbor
import com.lalameow.researchstation.Identifiers
import com.lalameow.researchstation.ResearchStation
import com.lalameow.researchstation.api.technology.TechnologyCategories
import com.lalameow.researchstation.api.technology.TechnologyCategory
import com.lalameow.researchstation.translatable
import com.lalameow.researchstation.util.serialization.TextAsJsonStringSerializer
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import net.fabricmc.api.EnvType
import net.fabricmc.api.Environment
import net.minecraft.item.ItemStack
import net.minecraft.text.Text
import net.minecraft.util.Identifier
import net.silkmc.silk.core.serialization.serializers.ResourceLocationSerializer
import net.silkmc.silk.nbt.serialization.serializer.ItemStackSerializer
import net.silkmc.silk.network.packet.c2sPacket
import net.silkmc.silk.network.packet.s2cPacket

@OptIn(ExperimentalSerializationApi::class)
internal object TechnologyCategoriesNetwork {
    val responsePacket = s2cPacket<List<Packet>>(Identifiers.TECHNOLOGY_CATEGORIES, ResearchStation.Cbor)
    val requestPacket = c2sPacket<Unit>(Identifiers.TECHNOLOGY_CATEGORIES, ResearchStation.Cbor)

    @Environment(EnvType.CLIENT)
    private val mutableCategories = MutableSharedFlow<List<Packet>>()

    @Environment(EnvType.CLIENT)
    val categories: SharedFlow<List<Packet>> = mutableCategories

    init {
        requestPacket.receiveOnServer { _, context ->
            responsePacket.send(
                TechnologyCategories.all().map { Packet(it) },
                context.player
            )
        }
        responsePacket.receiveOnClient { packet, _ ->
            mutableCategories.emit(packet)
        }
    }

    @Serializable
    internal data class Packet(
        val id: Identifier,
        val icon: Set<ItemStack>,
        val background: Identifier? = TechnologyCategory.DEFAULT_BACKGROUND,
        val name: Text = ResearchStation.translatable("category.$id"),
        val description: Text? = null
    ) {
        constructor(category: TechnologyCategory) : this(
            category.id,
            category.icon,
            category.background,
            category.name,
            category.description
        )
    }
}
